package org.kgduyjj.toolbox.handler;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 数据比较处理程序
 * 
 * @author Kgduyjj
 * @since 2020-07-26
 * @version Alpha-1.42
 *
 */
public class CompareHandler<T> {
	/** 原始数据源 */
	protected List<T> originalDatas;
	/** 被比较的数据 */
	protected List<T> compareDatas;

	/** 匹配数据 */
	protected List<T> matchList;
	/** 未匹配数据 */
	protected List<T> unmatchList;

	protected Set<T> sameDatas;
	protected Set<T> tempDatas;

	/** 是否已经做过比较算法 */
	protected Boolean compared;
	/** 比较器 */
	protected CustomComparer<T> comparer;
	/** 比较失败原因 */
	protected String compareFailureReason;

	public CompareHandler(List<T> originalDatas, List<T> compareDatas, CustomComparer<T> comparer) {
		this.originalDatas = originalDatas;
		this.compareDatas = compareDatas;
		this.comparer = comparer;
	}

	public CompareHandler(List<T> originalDatas, List<T> compareDatas) {
		this.originalDatas = originalDatas;
		this.compareDatas = compareDatas;
	}

	public List<T> getOriginalDatas() {
		return originalDatas;
	}

	public List<T> getCompareDatas() {
		return compareDatas;
	}

	public Boolean isCompared() {
		return (compared == null ? Boolean.FALSE : compared);
	}

	public String getCompareFailureReason() {
		return compareFailureReason;
	}

	public List<T> getMatchList() {
		return matchList;
	}

	public List<T> getUnmatchList() {
		return unmatchList;
	}

	private void compareFailure(String reason) {
		this.compareFailureReason = reason;
	}

	private void compared() {
		this.compared = Boolean.TRUE;
	}

	private void notCompared() {
		this.compared = Boolean.FALSE;
	}

	/**
	 * 判断是否存在比较器
	 * 
	 * @return
	 */
	public boolean hasComparer() {
		return (this.comparer == null);
	}

	/**
	 * 使用ArrayList的批量移除方案处理
	 * 
	 * @return
	 */
	private boolean _handlerWithArrayListMethod() {
		try {
			matchList = new ArrayList<T>(compareDatas);
			unmatchList = new ArrayList<T>(originalDatas);
			matchList.removeAll(originalDatas);
			unmatchList.removeAll(compareDatas);
			compared();
		} catch (Exception e) {
			compareFailure(e.getMessage());
			notCompared();
		}
		return compared;
	}

	/**
	 * 比较处理，使用HashSet的特性处理
	 * 
	 * @return
	 */
	@SuppressWarnings("unused")
	private boolean _handlerByHashSetMethod() {
		try {
			tempDatas = new HashSet<T>();
			tempDatas.addAll(originalDatas);
			for (T compareItem : compareDatas) {
				if (!tempDatas.add(compareItem)) {
					if (sameDatas == null)
						sameDatas = new HashSet<T>();
					sameDatas.add(compareItem);
				}
			}
			compared();
		} catch (Exception e) {
			compareFailure(e.getMessage());
			notCompared();
		}
		return compared;
	}

	/**
	 * 比较处理，不使用自定义比较器
	 * 
	 * @return
	 */
	public boolean compareNone() {
		if (this.originalDatas == null || this.compareDatas == null) {
			notCompared();
			return compared;
		}
		return _handlerWithArrayListMethod();
	}

	/**
	 * 添加匹配数据的Item
	 * 
	 * @param matchItem
	 * @return
	 */
	private boolean addMatchItem(T matchItem) {
		if (matchItem == null)
			return false;
		if (this.matchList == null)
			this.matchList = new ArrayList<T>(0);
		this.matchList.add(matchItem);
		return true;
	}

	/**
	 * 使用比较器比较数据
	 * 
	 * @param comparer
	 * @return
	 */
	public boolean compareWith(CustomComparer<T> comparer) {
		this.comparer = comparer;
		try {
			if ((this.originalDatas == null) || (this.compareDatas == null) || !hasComparer()) {
				notCompared();
				return compared;
			}
			for (T subject : originalDatas) {
				for (T comparison : compareDatas) {
					if (comparer.compareWith(subject, comparison)) {
						addMatchItem(subject);
					}
				}
			}
			compared();
		} catch (Exception e) {
			compareFailure(e.getMessage());
			notCompared();
		}
		return compared;
	}
}
